#ifndef BASE_CTMISC_H_
#define BASE_CTMISC_H_
#include "ctType.h"
#include "command.h"
#include <string>
#include <ctype.h>
#include <algorithm>
#include <time.h>
#include <vector>
#include <utility>
#include <ext/mt_allocator.h>
#include <queue>
#include <sstream>
#include <iconv.h>
#include <stdint.h>

/**
 * \brief ���ַ���tokenת��Ϊ����ַ�
 *
 * ������ʹ�����ӳ���
 *    <pre>
 *    std::list<string> ls;
 *    stringtok (ls," this  \t is\t\n  a test  ");
 *    for(std::list<string>const_iterator i = ls.begin(); i != ls.end(); ++i)
 *        std::cerr << ':' << (*i) << ":\n";
 *     </pre>
 *
 * \param container ���������ڴ���ַ�
 * \param in �����ַ�
 * \param delimiters �ָ����
 * \param deep ��ȣ��ָ����ȣ�ȱʡû������
 */
template<typename Container>
inline void
stringtok( Container &container, std::string const &in,
                const char * const delimiters = " \t\n",
                const int deep = 0 )
{
        const std::string::size_type len = in.length();
        std::string::size_type i = 0;
        int count = 0;

        while ( i < len ) {
                i = in.find_first_not_of( delimiters, i );
                if ( i == std::string::npos )
                        return;   // nothing left

                // find the end of the token
                std::string::size_type j = in.find_first_of( delimiters, i );

                count++;
                // push token
                if ( j == std::string::npos
                                || ( deep > 0 && count > deep ) ) {
                        container.push_back( in.substr( i ) );
                        return;
                }
                else
                        container.push_back( in.substr( i, j - i ) );

                // set up for next loop
                i = j + 1;
        }
}

/**
 * \brief ���ַ�ת��ΪСд�ĺ������
 *
 * ���磺
 * <pre>
 * std::string  s ("Some Kind Of Initial Input Goes Here");
 * std::transform (s.begin(),s.end(),s.begin(),ToLower());
 * </pre>
 */

struct ToLower
{
        char operator()( char c ) const {
                return tolower( c );
        }
};

/**
 * \brief ���ַ�ת��ΪСд
 * \param s ��Ҫת�����ַ�
 */
inline void to_lower( std::string &s )
{
        std::transform( s.begin(), s.end(), s.begin(), ToLower() );
}

/**
 * \brief ���ַ�ת��Ϊ��д�ĺ������
 *
 * ���磺
 * <pre>
 * std::string  s ("Some Kind Of Initial Input Goes Here");
 * std::transform (s.begin(),s.end(),s.begin(),ToUpper());
 * </pre>
 */
struct ToUpper
{
        char operator()( char c ) const {
                return toupper( c );
        }
};

/**
 * \brief ���ַ�ת��Ϊ��д
 * \param s ��Ҫת�����ַ�
 */
inline void to_upper( std::string &s )
{
        std::transform( s.begin(), s.end(), s.begin(), ToUpper() );
}

struct odds_t
{
        uint32_t upNum;
        uint32_t downNum;
};

//���ַ��в��ҵ�pos(���㿪ʼ)�����֣����δ�ҵ�����defValue
        template<typename T>
WORD getAllNum( const char *s, std::vector<T> & data )
{
        size_t i;
        int count = 0;
        if ( s == NULL ) {
                return count;
        }
        bool preIsD = false;
        for ( i = 0; i < strlen( s ); i++ ) {
                if ( isdigit( *( s + i ) ) ) {
                        if ( !preIsD ) {
                                count++;
                                data.push_back( atoi( s + i ) );
                        }
                        preIsD = true;
                }
                else
                        preIsD = false;
        }
        return count;
}

//������min~max֮������֣�����min��max
int randBetween( int min, int max );
//��ȡ����֮�ļ���
bool selectByOdds( const uint32_t upNum, const uint32_t downNum );
//��ȡ����֮���ļ���
bool selectByt_Odds( const odds_t &odds );
//��ȡ�ٷ�֮�ļ���
bool selectByPercent( const uint32_t percent );
//��ȡ�ٷ�֮�ļ���
bool selectByTenTh( const uint32_t tenth );
//��ȡ�ٷ�֮�ļ���
bool selectByLakh( const uint32_t lakh );
//��ȡ�ٷ�֮�ļ���
bool selectByOneHM( const uint32_t lakh );
//��ȡ��ǰʱ���ַ���Ҫ���ʽ
void getCurrentTimeString( char *buffer, const int bufferlen, const char *format );

char *getTimeString( time_t t, char *buffer, const int bufferlen, const char *format );

char *getTimeString( time_t t, char *buffer, const int bufferlen );

std::string version_ntoa(const DWORD &versionid);

uint32_t version_aton(const std::string &versionstr);

        template<typename T>
void convertString( std::string str, T& value )
{
        std::stringstream stream;
        stream.clear();
        stream << str;
        stream >> value;
}

        template<class T>
std::string value2str( const T _value )
{
        static std::stringstream ss;
        ss.str( "" );
        ss << _value;
        return ss.str();
}

std::string Str2Hex( const std::string data, bool bMakeLower );

//�ַ��滻
void replaceString( std::string& str, const std::string sought, const std::string replacement );
void trim_right( std::string& source, const std::string& t );
void trim_left( std::string& source, const std::string& t );

typedef std::pair<uint32_t, BYTE *> CmdPair;
template<int QueueSize = 102400>
class MsgQueue {
        public:
                MsgQueue() {
                        queueRead = 0;
                        queueWrite = 0;
                }
                ~MsgQueue() {
                        clear();
                }
                typedef std::pair<volatile bool, CmdPair> CmdQueue;
                CmdPair *get() {
                        CmdPair *ret = NULL;
                        if ( cmdQueue[queueRead].first ) {
                                ret = &cmdQueue[queueRead].second;
                        }
                        return ret;
                }
                void erase() {
                        __mt_alloc.deallocate( cmdQueue[queueRead].second.second, cmdQueue[queueRead].second.first );
                        cmdQueue[queueRead].first = false;
                        queueRead = ( ++queueRead ) % QueueSize;
                }
                bool put( const void *pNullCmd, const uint32_t cmdLen ) {
                        BYTE *buf = __mt_alloc.allocate( cmdLen );
                        if ( buf ) {
                                bcopy( pNullCmd, buf, cmdLen );
                                if ( !putQueueToArray() && !cmdQueue[queueWrite].first ) {
                                        cmdQueue[queueWrite].second.first = cmdLen;
                                        cmdQueue[queueWrite].second.second = buf;
                                        cmdQueue[queueWrite].first = true;
                                        queueWrite = ( ++queueWrite ) % QueueSize;
                                        return true;
                                }
                                else {
                                        queueCmd.push( std::make_pair( cmdLen, buf ) );
                                }
                                return true;
                        }
                        return false;

                }
        private:
                void clear() {
                        while ( putQueueToArray() ) {
                                while ( get() ) {
                                        erase();
                                }
                        }
                        while ( get() ) {
                                erase();
                        }
                }
                bool putQueueToArray() {
                        bool isLeft = false;
                        while ( !queueCmd.empty() ) {
                                if ( !cmdQueue[queueWrite].first ) {
                                        cmdQueue[queueWrite].second = queueCmd.front();
                                        ;
                                        cmdQueue[queueWrite].first = true;
                                        queueWrite = ( ++queueWrite ) % QueueSize;
                                        queueCmd.pop();
                                }
                                else {
                                        isLeft = true;
                                        break;
                                }
                        }
                        return isLeft;
                }
                __gnu_cxx:: __mt_alloc <BYTE> __mt_alloc;
                CmdQueue cmdQueue[QueueSize];
                std::queue<CmdPair> queueCmd;
                uint32_t queueWrite;
                uint32_t queueRead;
};

class MessageQueue
{
        protected:
                virtual ~MessageQueue() {
                }
                ;
        public:
                bool msgParse( const Cmd::t_NullCmd *pNullCmd, const uint32_t cmdLen ) {
                        return cmdQueue.put( ( void* ) pNullCmd, cmdLen );
                }
                virtual bool cmdMsgParse( const Cmd::t_NullCmd *, const uint32_t )=0;
                bool doCmd() {
                        CmdPair *cmd = cmdQueue.get();
                        while ( cmd ) {
                                cmdMsgParse( ( const Cmd::t_NullCmd * ) cmd->second, cmd->first );
                                cmdQueue.erase();
                                cmd = cmdQueue.get();
                        }
                        if ( cmd ) {
                                cmdQueue.erase();
                        }
                        return true;
                }

        private:
                MsgQueue<> cmdQueue;
};

#endif //BASE_CTMISC_H_
